#ifndef __THREADPOOL_H_
#define __THREADPOOL_H_

#include<vector>
#include<queue>
#include<memory>
#include<atomic>
#include<mutex>
#include<condition_variable>
#include<functional>
#include<iostream>
#include<unordered_map>
#include<future>
#include<thread>


// 线程池支持的模式
enum class PoolMode
{
	MODE_FIXED,
	MODE_CACHED
};

// 线程类型
class Thread
{
public:
	using ThreadFunc = std::function<void(int)>;  // 定义线程函数对象类型别名
	Thread(ThreadFunc func);
	~Thread();
	void start();
	int getId() const;  // 获取线程ID
private:
	ThreadFunc func_;  // 线程函数
	static int generateId_;
	int threadId_;  // 保存线程id
};

// 线程池类型
class ThreadPool
{
public:
	ThreadPool();
	~ThreadPool();

	// 设置线程池的工作模式
	void setMode(PoolMode mode);

	// 设置初始的线程数量
	void setInitThreadSize(size_t size);

	// 设置task任务队列上限阈值
	void setTaskQueMaxThreshHold(int threshhold);

	// 设置线程池cached模式下线程对象上限
	void setThreadSizeThreshold(int threshold);

	// 给线程池提交任务
	template<typename F, typename... Args>
	auto submitTask(F&& callable, Args&&... args)
		-> std::future<decltype(callable(args...))>
	{
		using Return_type = decltype(callable(args...));
		auto task = std::make_shared<std::packaged_task<Return_type()>>(
			std::bind(std::forward<F>(callable), std::forward<Args>(args)...)
		);
		std::future<Return_type> res = task->get_future();
		{
			std::unique_lock<std::mutex> lock(taskQueMtx_);
			if (!notFull_.wait_for(lock, std::chrono::seconds(1),
				[this]()->bool {return taskQue_.size() < taskQueMaxThreshold_; }))
			{
				std::cout << "task submit fail!" << std::endl;
				auto task = std::packaged_task<Return_type()>(
					[]() {return Return_type(); }
				);
				auto res = task.get_future();
				task();
				return res;
			}
			taskQue_.emplace([task]() { (*task)(); });
		}
		
		return res;
	}

	// 开启线程池
	void start(int initThreadSize = std::thread::hardware_concurrency());  // 初始线程数量为硬件核心数量

	ThreadPool(const ThreadPool&) = delete;
	ThreadPool& operator=(const ThreadPool&) = delete;

private:
	// 定义线程函数
	void threadFunc(int threadid);
	// 检查pool的运行状态
	bool checkRunningState() const;
private:
	std::unordered_map<int, std::unique_ptr<Thread>> threads_;  // 线程容器
	int initThreadSize_; // 初始线程数量
	std::atomic_int curThreadSize_;  // 当前线程数量
	int threadSizeThreshold_;  // 线程数量上限阈值
	std::atomic_int idleThreadSize_;  // 记录空闲线程数量

	std::queue<std::function<void()>> taskQue_;  // 任务队列
	std::atomic<size_t> taskSize_; // 任务数量
	int taskQueMaxThreshold_;  // 任务队列数量上限阈值

	std::mutex taskQueMtx_;  // 保证任务队列的线程安全
	std::condition_variable notFull_;  // 表示任务队列不满
	std::condition_variable notEmpty_;  // 表示任务队列不空
	std::condition_variable exitCond_;  // 等待线程资源全部回收

	PoolMode poolMode_;  // 当前线程池的工作模式

	// 表示当前线程池的启动状态
	std::atomic_bool isPoolRunning_;
};

#endif